Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support computing values for all rational powers #213

Merged
merged 6 commits into from
Dec 19, 2023

Conversation

chiphogg
Copy link
Contributor

I thought we would need to wait for a constexpr version of
std::powl, but I was wrong. Instead, we can get away with a root
function. Note that there's no guarantee that std::powl would be
better in all cases, even if we could just use it. After all, its
second argument is 1.0l / n, which is a lossy representation of the
Nth root.

On the implementation side, we take advantage of the fact that this
function is only ever meant to be called at compile time, which lets us
prioritize accuracy over "speed" (because the runtime speed is always
essentially infinite). We do a binary search between 1 and x after
checking that x > 1 (and n > 1). When we end up with two
neighboring floating point values, we pick whichever gives the closest
result when we run it through checked_int_pow.

This algorithm is guaranteed to produce the best representable result
for a "pure root". For other rational powers, it's technically possible
that we could have some lossiness in the checked_int_pow computation,
if we enter a floating point realm that is high enough such that not all
integer values can be represented. That said, I tried a bunch of test
cases to compare it to powl, and it's passed all the ones that I was
able to come up with.

Fixes #116.

I thought we would need to wait for a `constexpr` version of
`std::powl`, but I was wrong.  Instead, we can get away with a `root`
function.  Note that there's no guarantee that `std::powl` would be
better in all cases, even if we _could_ just use it.  After all, its
second argument is `1.0l / n`, which is a lossy representation of the
Nth root.

On the implementation side, we take advantage of the fact that this
function is only ever meant to be called at compile time, which lets us
prioritize accuracy over "speed" (because the runtime speed is always
essentially infinite).  We do a binary search between 1 and `x` after
checking that `x > 1` (and `n > 1`).  When we end up with two
neighboring floating point values, we pick whichever gives the closest
result when we run it through `checked_int_pow`.

This algorithm is guaranteed to produce the best representable result
for a "pure root".  For other rational powers, it's technically possible
that we could have some lossiness in the `checked_int_pow` computation,
if we enter a floating point realm that is high enough such that not all
integer values can be represented.  That said, I tried a bunch of test
cases to compare it to `powl`, and it's passed all the ones that I was
able to come up with.

Fixes #116.
@chiphogg chiphogg added the release notes: 🐛 lib (bugfix) PR fixing a defect in the library code label Dec 18, 2023
@chiphogg chiphogg requested a review from geoffviola December 18, 2023 20:36
@chiphogg chiphogg requested a review from geoffviola December 18, 2023 22:52
Copy link
Contributor

@geoffviola geoffviola left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Algorithm makes sense. New API looks useful. Tests look good.

au/magnitude.hh Show resolved Hide resolved
au/magnitude_test.cc Outdated Show resolved Hide resolved
au/magnitude_test.cc Outdated Show resolved Hide resolved
@chiphogg chiphogg merged commit 7d8a544 into main Dec 19, 2023
9 checks passed
@chiphogg chiphogg deleted the chiphogg/rational-value#116 branch December 19, 2023 16:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release notes: 🐛 lib (bugfix) PR fixing a defect in the library code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support value conversion with rational exponents
2 participants